using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

/* Ask RIL for celltower infos 
 * Attention: Quick hack
*/

/* (c) "Neil Young" (neil.young@freenet.de)
 * 
 * This script/program is provided "as is".
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * GNU General Public License, see <http://www.gnu.org/licenses/>.
 */

namespace RIL {
    public class RIL {
        public delegate void RILRESULTCALLBACK(int dwCode, IntPtr hrCmdID, IntPtr lpData, int cbData, int dwParam);
        public delegate void RILNOTIFYCALLBACK(int dwCode, IntPtr lpData, int cbData, int dwParam);

        [StructLayout(LayoutKind.Explicit)]
        class RILCELLTOWERINFO {
            [FieldOffset(0)]
            uint dwLen;
            [FieldOffset(4)]
            uint dwParams;
            [FieldOffset(8)]
            public uint dwMobileCountryCode;
            [FieldOffset(12)]
            public uint dwMobileNetworkCode;
            [FieldOffset(16)]
            public uint dwLocationAreaCode;
            [FieldOffset(20)]
            public uint dwCellID;
            [FieldOffset(24)]
            uint dwBaseStationID;
            [FieldOffset(28)]
            uint dwBroadcastControlChannel;
            [FieldOffset(32)]
            uint dwRxLevel;
            [FieldOffset(36)]
            uint dwRxLevelFull;
            [FieldOffset(40)]
            uint dwRxLevelSub;
            [FieldOffset(44)]
            uint dwRxQuality;
            [FieldOffset(48)]
            uint dwRxQualityFull;
            [FieldOffset(52)]
            uint dwRxQualitySub;
			/* More minor interesting fields below */
        }

        private static bool done = false;
        private static string result = "";

        [DllImport("ril.dll")]
        private static extern IntPtr RIL_Initialize(int dwIndex, RILRESULTCALLBACK pfnResult, RILNOTIFYCALLBACK pfnNotify, int dwNotificationClasses, int dwParam, out IntPtr lphRil);

        [DllImport("ril.dll", EntryPoint = "RIL_DevSpecific")]
        private static extern IntPtr RIL_DevSpecific(IntPtr hRil, IntPtr dwParam, IntPtr size);

        [DllImport("ril.dll", EntryPoint = "RIL_GetCellTowerInfo")]
        private static extern IntPtr RIL_GetCellTowerInfo(IntPtr hRil);

        [DllImport("ril.dll")]
        private static extern IntPtr RIL_Deinitialize(IntPtr hRil);

        public static void f_notify(int dwCode, IntPtr lpData, int cbData, int dwParam) {
        }

        public static void f_result(int dwCode, IntPtr hrCmdID, IntPtr lpData, int cbData, int dwParam) {
            RILCELLTOWERINFO rci = new RILCELLTOWERINFO();
            Marshal.PtrToStructure(lpData, rci);

            result = String.Format("MCC: {0}, MNC: {1}, CID: {2}, LAC: {3}",
                rci.dwMobileCountryCode,
                rci.dwMobileNetworkCode,
                rci.dwLocationAreaCode,
                rci.dwCellID);
            done = true;
        }


        public static string GetCellTowerInfo() {
            IntPtr hRil, res;

            RILRESULTCALLBACK result = new RILRESULTCALLBACK(f_result);
            RILNOTIFYCALLBACK notify = new RILNOTIFYCALLBACK(f_notify);

            res = RIL_Initialize(1, result, notify, 0, 0, out hRil);
            if (res != IntPtr.Zero)
                return ("Could not initialize Ril");
            RIL.done = false;
            RIL.result = "";
            res = RIL_GetCellTowerInfo(hRil);
            int i = 10;
            while (i-- > 0 && !RIL.done) {
                System.Threading.Thread.Sleep(1000);
            }

            RIL_Deinitialize(hRil);
            return RIL.result;
        }
    }


    class Program {
        static void Main(string[] args) {
            string s = RIL.GetCellTowerInfo();
            MessageBox.Show(s);
        }
    }
}
